using System;
using System.Collections;
using System.Collections.Generic;
using Newtonsoft.Json;
using FreeRedis;

namespace QQZiFramework
{


    public class RedisAccess:IDisposable
    {
        static RedisConfig _redisConfig;

        static string[] _redisHost;

        // /// <summary>
        // /// 初始化Redis配置
        // /// </summary>
        // /// <param name="host"></param>
        // /// <param name="port"></param>
        // public static void SetRedis(string host, int port, string pwd, int pool)
        // {
        //     SetRedis(host, port, pwd, true, pool, 10000);
        // }

        /// <summary>
        /// 初始化Redis配置
        /// </summary>
        /// <param name="host"></param>
        /// <param name="port"></param>
        public static void SetRedis(string host, int port, string pwd, int pool, bool log)
        {
            SetRedis(new RedisConfig { IP = host, Port = port, Password = pwd, Log = log, MinPool = pool, MaxPool = 10000 });
        }
        /// <summary>
        /// 初始化Redis配置
        /// </summary>
        /// <param name="host"></param>
        /// <param name="port"></param>
        public static void SetRedis(RedisConfig config)
        {
            DBContext.UserRedis = true;
            DBContext.Default_Redis_Database_Index = config.Default;
            if (config.IP == null) config.IP = "127.0.0.1";
            _redisHost = config.IP.Split(',');
            if (config.Port < 1) config.Port = 6379;
            if (config.Password == "") config.Password = null;
            _redisConfig = config;

            // fRedisConfig = new ConfigurationOptions()
            // {
            //     Password = _redisConfig.Password,
            //     EndPoints = { { redisHostArray, _redisConfig.Port } },
            //     AllowAdmin = true,
            //     ConnectTimeout = 15000,
            //     SyncTimeout = 30000
            // }; 
            SUBSCRIBER_CLIENT = CreateClient(0);// new RedisClient(connStr,new ConnectionStringBuilder[] { "10.10.90.252:6379", "10.10.90.200:6379", "10.10.90.226:6379" });


            // bool connected = SUBSCRIBER_CLIENT.con(15000);
            // if (!connected) throw new Exception("redis 连接异常!");
            // connected = DEFAULT_REDIS_CLIENT.Connect(15000);
        }

        //static ConfigurationOptions fRedisConfig;

        static RedisClient SUBSCRIBER_CLIENT;


        static Dictionary<int, RedisClient> DEFAULT_REDIS_CLIENT = new Dictionary<int, RedisClient>();
        RedisClient RedisClient
        {
            get
            {
                if (client == null) client = CreateClient(mDataBaseIndex);
                return client;
                //RedisClient client;
                //if (!DEFAULT_REDIS_CLIENT.TryGetValue(mDataBaseIndex, out client) || client == null)
                //{
                //    //如果缓存获取失败，重新初始
                //    if (client == null && DEFAULT_REDIS_CLIENT.ContainsKey(mDataBaseIndex))
                //    {
                //        DEFAULT_REDIS_CLIENT.Remove(mDataBaseIndex);
                //    }
                //    Set_DEFAULT_REDIS_CLIENTS();
                //    client = DEFAULT_REDIS_CLIENT[mDataBaseIndex];
                //}
                //return client;
            }
        }

        DBContext context;

        RedisClient client;
        public RedisAccess(DBContext context)
        {
            this.context = context;
        }
        public int mDataBaseIndex = -1;

        public int DataBaseIndex
        {
            get { return mDataBaseIndex; }
            set
            {
                mDataBaseIndex = value;
                if(client!=null) client.Dispose();  
                client = null;
                //Set_DEFAULT_REDIS_CLIENTS();
            }
        }

        //private void Set_DEFAULT_REDIS_CLIENTS()
        //{
        //    lock (DEFAULT_REDIS_CLIENT)
        //    {
        //        if (!DEFAULT_REDIS_CLIENT.ContainsKey(mDataBaseIndex))
        //        {
        //            DEFAULT_REDIS_CLIENT.Add(mDataBaseIndex, CreateClient(mDataBaseIndex));
        //            context.LogDebug("create redis client instance of db " + mDataBaseIndex, "redis");
        //        }
        //    }
        //}

        private static RedisClient CreateClient(int db)
        {
            if (_redisHost.Length > 1)
            {
                //集群
                var connStrArray = new ConnectionStringBuilder[_redisHost.Length];
                for (int i = 0; i < connStrArray.Length; i++)
                {
                    var connTemp = _redisHost[i];
                    if (_redisHost[i].IndexOf(":") == -1) connTemp += ":" + _redisConfig.Port;
                    connStrArray[i] = convertConfig(connTemp, db);
                }
                return new RedisClient(connStrArray);
            }
            else
            {
                return new RedisClient(convertConfig(_redisConfig.IP + ":" + _redisConfig.Port, db));
            }

        }

        private static ConnectionStringBuilder convertConfig(string hostAndPort, int db)
        {
            var connTemp = hostAndPort;
            if (!String.IsNullOrEmpty(_redisConfig.Password))
            {
                connTemp += ",password=" + _redisConfig.Password;
            }
            var conn = ConnectionStringBuilder.Parse(connTemp);
            conn.Database = db;
            if (_redisConfig.MinPool > 0)
            {
                conn.MinPoolSize = _redisConfig.MinPool;
                conn.MaxPoolSize = _redisConfig.MaxPool;
            }
            if (_redisConfig.ConnectTimeout > 0) conn.ConnectTimeout = TimeSpan.FromMilliseconds(_redisConfig.ConnectTimeout);
            if (_redisConfig.SendTimeout > 0) conn.SendTimeout = TimeSpan.FromMilliseconds(_redisConfig.SendTimeout);
            if (_redisConfig.ReceiveTimeout > 0) conn.ReceiveTimeout = TimeSpan.FromMilliseconds(_redisConfig.ReceiveTimeout);
            if (_redisConfig.IdleTimeout > 0) conn.IdleTimeout = TimeSpan.FromMilliseconds(_redisConfig.IdleTimeout);
            return conn;
        }

        /// <summary>
        /// 取消订阅
        /// </summary>
        public static void UnSubscribe(string channel)
        {
            SUBSCRIBER_CLIENT.UnSubscribe(channel);
        }

        /// <summary>
        /// 订阅
        /// </summary>
        public static void Subscribe(string channel, Action<string> action)
        {

            SUBSCRIBER_CLIENT.Subscribe(channel, (s, e) =>
             {
                 action(e.ToString());
             });

        }

        /// <summary>
        /// 发布
        /// </summary>
        public static void Publish(string channel, object item)
        {

            Type type = item.GetType();
            string itemJson;
            if (type.IsValueType || type == typeof(string))
            {
                itemJson = item.ToString();
            }
            else
            {
                if (item is IDBEntity) itemJson = (item as IDBEntity).ToJson();
                else itemJson = JsonConvert.SerializeObject(item);
            }
            SUBSCRIBER_CLIENT.Publish(channel, itemJson);
        }


        public T GetRedisItem<T>(string key, bool throwNull = true)
        {
            key = context.Membership.OnRedisKey(key);
            if (_redisConfig.LogGet) context.LogDebug("获取" + key, "缓存");
            Type type = typeof(T);
            T result;
            string str = RedisClient.Get(key);
            if (str == null)
            {
                if (throwNull) throw new ClientException("缓存中没有" + key);
                else return default(T);
            }
            //byte[] bytes = redisClient.Get(key);
            //if (bytes == null || bytes.Length == 0)
            //{
            //    if (throwNull) throw new ClientException("缓存中没有" + key);
            //    return default(T);
            //}
            //string str = UTF8Encoding.Default.GetString(bytes);
            if (type.IsValueType || type == typeof(string))
            {
                result = (T)Convert.ChangeType(str, typeof(T));
                return result;
            }
            else
            {
                return JsonConvert.DeserializeObject<T>(str);
            }
        }

        /// <summary>
        /// 获取Redis中的指定类型的缓存信息
        /// <param name="key">redis中的键</param>
        /// </summary>
        public object GetItemFromCache(Type type, string key, bool throwNull = true)
        {
            key = context.Membership.OnRedisKey(key);

            ////IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            string str = RedisClient.Get(key);
            if (str == null)
            {
                if (throwNull) throw new ClientException("缓存中没有" + key);
                else return null;
            }
            return Newtonsoft.Json.JsonConvert.DeserializeObject(str, type);
        }

        public List<string> FindKeys(string pattern)
        {
            string pattern2 = context.Membership.OnRedisKey(pattern);

            if (_redisConfig.LogGet) context.LogDebug("查找" + pattern2, "缓存");
            //IServer server = RedisClient.GetServer(RedisClient.GetEndPoints()[0]);
            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            List<string> lst = new List<string>();
            string onKeyDiff = pattern2.Replace(pattern, "");
            foreach (var key in RedisClient.Keys(pattern2))
            {
                if (onKeyDiff.Length > 0)
                    lst.Add(key.Replace(onKeyDiff, ""));
                else
                    lst.Add(key);
            }
            return lst;
        }

        /// <summary>
        /// 查询Redis中的指定类型的缓存信息
        /// </summary>
        /// <param name="type"></param>
        /// <param name="pattern">比如session:*</param>
        /// <returns>匹配项值的集合，不是key的集合</returns>
        public Dictionary<string, T> FindRedis<T>(string pattern)
        {
            pattern = context.Membership.OnRedisKey(pattern);

            if (_redisConfig.LogGet) context.LogDebug("查找" + pattern, "缓存");
            // else System.Diagnostics.Debug.WriteLine("查找" + pattern, "缓存");
            Type type = typeof(T);
            //IServer server = RedisClient.GetServer(RedisClient.GetEndPoints()[0]);
            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            Dictionary<string, T> dic = new Dictionary<string, T>();
            foreach (var key in RedisClient.Keys(pattern))
            {
                string str = RedisClient.Get(key); //UTF8Encoding.Default.GetString(values[i]);
                if (str == null) continue;
                if (type.IsValueType || type == typeof(string))
                {
                    dic.Add(key, (T)Convert.ChangeType(str, type));
                }
                else
                {
                    dic.Add(key, JsonConvert.DeserializeObject<T>(str));
                }
            }
            return dic;
        }

        public int DeleteRedisItems(string pattern)
        {

            pattern = context.Membership.OnRedisKey(pattern);
            //IServer server = RedisClient.GetServer(RedisClient.GetEndPoints()[0]);
            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            int cc = 0;
            foreach (var key in RedisClient.Keys(pattern))
            {
                RedisClient.Del(key);
                cc++;
            }
            return cc;

        }

        public void DeleteRedisItem(string key)
        {
            key = context.Membership.OnRedisKey(key);

            if (_redisConfig.Log) context.LogDebug("删除" + key, "缓存");
            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            RedisClient.Del(key);
        }

        public static readonly object lockObj = new object();

        public void SetRedisItem(string key, object item, DateTime? expiresAt = null)
        {
            if (item == null)
            {
                DeleteRedisItem(key);
                return;
            }
            key = context.Membership.OnRedisKey(key);

            string itemJson;

            Type type = item.GetType();
            if (type.IsValueType || type == typeof(string))
            {
                itemJson = item.ToString();
            }
            else
            {
                if (item is IDBEntity) itemJson = (item as IDBEntity).ToJson();
                else itemJson = JsonConvert.SerializeObject(item);
            }
            if (_redisConfig.Log) context.LogDebug("设置" + key + "：" + itemJson, "缓存");
            // else System.Diagnostics.Debug.WriteLine("设置" + key + "：" + itemJson + key, "缓存");
            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);

            // (RedisClient)
            // {
            if (expiresAt != null)
            {
                //TimeSpan ts = TimeSpan.FromMinutes((expiresAt.Value - DateTime.Now).TotalMinutes);
                RedisClient.Set(key, itemJson, (int)(expiresAt.Value - DateTime.Now).TotalSeconds);
            }
            else RedisClient.Set(key, itemJson);
            // }
        }
        #region list
        public List<T> GetList<T>(string lstName, int top)
        {
            lstName = context.Membership.OnRedisKey(lstName);

            if (_redisConfig.LogGet) context.LogDebug("获取" + lstName, "缓存");
            // else System.Diagnostics.Debug.WriteLine("获取" + lstName, "缓存");
            Type type = typeof(T);
            List<T> ht = new List<T>();
            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            int index = 0;
            foreach (var hashEntry in RedisClient.LRange(lstName, 0, 100000))
            {
                index++;
                if (top != -1 && index > top) break;
                T result;
                if (type.IsValueType || type == typeof(string))
                {
                    result = (T)Convert.ChangeType(hashEntry.ToString(), typeof(T));
                }
                else
                {
                    result = JsonConvert.DeserializeObject<T>(hashEntry.ToString());
                }
                ht.Add(result);
            }
            return ht;
        }

        public T GetListItem<T>(string hashName, long index, bool throwNull = true)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            if (_redisConfig.LogGet) context.LogDebug("获取列表" + hashName + ":" + index, "缓存");
            Type type = typeof(T);
            T result;
            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            string str = RedisClient.LIndex(hashName, index);
            if (str == null)
            {
                if (throwNull) throw new ClientException("缓存中没有" + hashName);
                else return default(T);
            }
            if (type.IsValueType || type == typeof(string))
            {
                result = (T)Convert.ChangeType(str, typeof(T));
                return result;
            }
            else
            {
                return JsonConvert.DeserializeObject<T>(str);
            }
        }
        public T PopListItem<T>(string hashName)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            Type type = typeof(T);
            T result;
            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            string str = RedisClient.LPop(hashName);
            if (str == null)
            {
                return default(T);
            }
            if (type.IsValueType || type == typeof(string))
            {
                result = (T)Convert.ChangeType(str, typeof(T));
                return result;
            }
            else
            {
                return JsonConvert.DeserializeObject<T>(str);
            }
        }

        public void SetListItem(string lstName, object item)
        {
            if (item == null) return;
            lstName = context.Membership.OnRedisKey(lstName);

            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            string itemJson;
            Type type = item.GetType();
            if (type.IsValueType || type == typeof(string))
            {
                itemJson = item.ToString();
            }
            else
            {
                if (item is IDBEntity) itemJson = (item as IDBEntity).ToJson();
                else itemJson = JsonConvert.SerializeObject(item);
            }
            if (_redisConfig.Log) context.LogDebug("list添加：" + lstName, "缓存");
            lock (lockObj)
            {
                RedisClient.RPush(lstName, itemJson);
            }
        }

        public long GetListLength(string lstName)
        {
            lstName = context.Membership.OnRedisKey(lstName);

            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            return RedisClient.LLen(lstName);
        }

        public void DeleteListItem(string hashName, string itemValue)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            if (_redisConfig.Log) context.LogDebug("删除List," + hashName + ":" + itemValue, "缓存");
            RedisClient.LRem(hashName, 1, itemValue);
        }
        #endregion

        #region set (collection)
        /// <summary>
        ///获取set集合
        /// </summary>
        /// <param name="key"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T[] CollectionGetALL<T>(string key)
        {
            key = context.Membership.OnRedisKey(key);
            if (_redisConfig.LogGet) context.LogDebug("获取" + key, "缓存");
            // else System.Diagnostics.Debug.WriteLine("获取" + key, "缓存");
            Type type = typeof(T);
            string[] arr = RedisClient.SMembers(key);
            T[] resultArr = new T[arr.Length];
            for (int i = 0; i < arr.Length; i++)
            {
                T item;
                if (type.IsValueType || type == typeof(string))
                {
                    item = (T)Convert.ChangeType(arr[i], typeof(T));
                }
                else
                {
                    item = JsonConvert.DeserializeObject<T>(arr[i]);
                }
                resultArr[i] = item;
            }
            return resultArr;
        }

        /// <summary>
        /// set集合添加一个或多个项
        /// </summary>
        /// <param name="key"></param>
        /// <param name="values"></param>
        public void CollectionAdd(string key, object[] values)
        {
            if (values == null || values.Length == 0) return;
            key = context.Membership.OnRedisKey(key);
            // string[] arr = new string[values.Length];
            // Type type = values[0].GetType();
            // if (type.IsValueType || type == typeof(string))
            // {
            //     for (int i = 0; i < values.Length; i++) arr[i] = values[i].ToString();
            // }
            // else
            // {
            //     for (int i = 0; i < values.Length; i++) arr[i] = JsonConvert.SerializeObject(values[i]);
            // }
            if (_redisConfig.Log) context.LogDebug("set添加：" + key + "," + values[0] + "等", "缓存");
            lock (lockObj)
            {
                RedisClient.SAdd(key, values);
            }
        }
        /// <summary>
        /// set集合添加,移除一个或多个项
        /// </summary>
        /// <param name="key"></param>
        /// <param name="values"></param>
        public void CollectionRemove(string key, params object[] values)
        {
            if (values == null || values.Length == 0) return;
            key = context.Membership.OnRedisKey(key);
            context.LogDebug("set移除：" + key + "," + values[0] + "等", "缓存");
            lock (lockObj)
            {
                RedisClient.SRem(key, values);
            }
        }

        /// <summary>
        /// 返回set集合的长度
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public long CollectionLength(string key)
        {
            key = context.Membership.OnRedisKey(key);
            return RedisClient.SCard(key);
        }
        #endregion



        #region Hash

        public T GetHashItem<T>(string hashName, string itemKey, bool throwNull = true)
        {
            hashName = context.Membership.OnRedisKey(hashName);
            if(_redisConfig.LogGet) context.LogDebug("获取" + hashName + ":" + itemKey, "缓存");
            Type type = typeof(T);
            T result;
            string str = null;
            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);           
            str = RedisClient.HGet(hashName, itemKey);
            if (str == null)
            {
                if (throwNull) throw new ClientException(hashName + "缓存中没有" + itemKey);
                else return default(T);
            }
            if (type.IsValueType || type == typeof(string))
            {
                result = (T)Convert.ChangeType(str, typeof(T));
                return result;
            }
            else
            {
                return JsonConvert.DeserializeObject<T>(str);
            }

        }

        public long GetHashLength(string hashName)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            return RedisClient.HLen(hashName);
        }

        public void SetHashItem(string hashName, string itemKey, object item)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);

            if (item == null)
            {
                RedisClient.HDel(hashName, itemKey);
            }
            string itemJson;
            Type type = item.GetType();
            if (type.IsValueType || type == typeof(string))
            {
                itemJson = item.ToString();
            }
            else
            {
                if (item is IDBEntity) itemJson = (item as IDBEntity).ToJson();
                else itemJson = JsonConvert.SerializeObject(item);
            }
            if (_redisConfig.Log) context.LogDebug("设置hash," + hashName + " ," + itemKey + ":" + itemJson, "缓存");
            RedisClient.HSet(hashName, itemKey, itemJson);

        }
        public void HashIncrement(string hashName, string itemKey, long increment = 1)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            RedisClient.HIncrBy(hashName, itemKey, increment);
        }

        public void DeleteHashItem(string hashName, string itemKey)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            if (_redisConfig.Log) context.LogDebug("删除Hash," + hashName + ":" + itemKey, "缓存");
            RedisClient.HDel(hashName, itemKey);
        }

        public bool HashExists(string hashName, string itemKey)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            return RedisClient.HExists(hashName, itemKey);
        }

        public string[] HashKeys(string hashName)
        {
            hashName = context.Membership.OnRedisKey(hashName);
            return RedisClient.HKeys(hashName);
        }

        /// <summary>
        /// 使用HSCAN检索Hash
        /// </summary>
        /// <typeparam name="T">值的类型，不能是object，可以是string</typeparam>
        /// <param name="patten">匹配</param>
        /// <param name="top">返回多少条数据，必填</param>
        public Hashtable HashFind<T>(string hashName, string patten, long top, Predicate<T> match = null)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            if (_redisConfig.LogGet) context.LogDebug("获取" + hashName, "缓存");
            //else System.Diagnostics.Debug.WriteLine("获取" + hashName, "缓存");
            Type type = typeof(T);
            Hashtable ht = new Hashtable();
            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            int index = 0;
            string[] array = RedisClient.HScan(hashName, 0, patten, top).items;
            for (int i = 0; i < array.Length; i++)
            {
                string key = array[i];
                string str = array[++i];
                T result;
                if (type.IsValueType || type == typeof(string))
                {
                    result = (T)Convert.ChangeType(str, typeof(T));

                }
                else
                {
                    result = JsonConvert.DeserializeObject<T>(str);
                }

                if (match != null)
                {
                    if (match.Invoke(result))
                    {
                        ht.Add(key, result);
                        index++;
                    }
                }
                else
                {
                    index++;

                    ht.Add(key, result);
                }
                if (top != -1 && index > top) break;
            }
            return ht;
        }

        #endregion

        #region SortedSetAdd

        public long GetSortedSetLength(string hashName)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            return RedisClient.ZCard(hashName);
        }

        public T[] SortedSetTop<T>(string hashName, long top = 1)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);

            ZMember[] arr = RedisClient.ZRevRangeWithScores(hashName, 0L, top - 1);
            T[] returnArr = new T[arr.Length];
            Type type = typeof(T);
            for (int i = 0; i < arr.Length; i++)
            {
                //if (arr[i].HasValue == false) continue;
                if (type.IsValueType || type == typeof(string))
                {
                    returnArr[i] = (T)Convert.ChangeType(arr[i].member, typeof(T));
                }
                else
                {
                    returnArr[i] = JsonConvert.DeserializeObject<T>(arr[i].member);
                }
            }
            return returnArr;
        }

        public T[] SortedSetGetRange<T>(string hashName, double scoreBegin, double scoreEnd, int top = -1)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            var arr = RedisClient.ZRevRangeByScore(hashName, (decimal)scoreBegin, (decimal)scoreEnd, 0, top);
            T[] returnArr = new T[arr.Length];
            Type type = typeof(T);
            for (int i = 0; i < arr.Length; i++)
            {
                //if (arr[i].HasValue == false) continue;
                if (type.IsValueType || type == typeof(string))
                {
                    returnArr[i] = (T)Convert.ChangeType(arr[i], typeof(T));
                }
                else
                {
                    returnArr[i] = JsonConvert.DeserializeObject<T>(arr[i]);
                }
            }
            return returnArr;
        }

        public void AddSortedSetItem<T>(string hashName, decimal score, T item)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);

            string itemJson;
            Type type = typeof(T);
            if (type.IsValueType || type == typeof(string))
            {
                itemJson = item.ToString();
            }
            else
            {
                if (item is IDBEntity) itemJson = (item as IDBEntity).ToJson();
                else itemJson = JsonConvert.SerializeObject(item);
            }
            if (_redisConfig.Log) context.LogDebug("设置SortedSet," + hashName + " ," + score + ":" + itemJson, "缓存");
            //client.SortedSetAdd(hashName, itemJson, score);
            RedisClient.ZAdd(hashName, score, itemJson);
        }


        public void DeleteSortedSetItem(string hashName, decimal score)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            if (_redisConfig.Log) context.LogDebug("删除SortedSet," + hashName + ":" + score, "缓存");
            //client.SortedSetRemoveRangeByScore(hashName, score, score);
            RedisClient.ZRemRangeByScore(hashName, score, score);
        }

        public Hashtable SortedSetScan<T>(string hashName, int top = -1, Predicate<T> match = null)
        {
            hashName = context.Membership.OnRedisKey(hashName);

            if (_redisConfig.LogGet) context.LogDebug("获取" + hashName, "缓存");
            // else System.Diagnostics.Debug.WriteLine("获取" + hashName, "缓存");
            Type type = typeof(T);
            Hashtable ht = new Hashtable();
            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            int index = 0;
            foreach (var hashEntry in RedisClient.ZRevRangeWithScores(hashName, 0M, (decimal)top))
            {
                T result;
                if (type.IsValueType || type == typeof(string))
                {
                    result = (T)Convert.ChangeType(hashEntry.member, typeof(T));
                }
                else
                {
                    result = JsonConvert.DeserializeObject<T>(hashEntry.member);
                }
                if (match != null)
                {
                    if (match.Invoke(result))
                    {
                        ht.Add(hashEntry.score, result);
                        index++;
                    }
                }
                else
                {
                    index++;

                    ht.Add(hashEntry.score, result);
                }
                if (top != -1 && index > top) break;
            }
            return ht;
        }
        #endregion



        public TItem GetOrCreate<TItem>(string key, Func<RedisOption, TItem> factory)
        {
            string str = GetRedisItem<string>(key, false);
            TItem t;
            Type type = typeof(TItem);
            if (str == null)
            {
                RedisOption option = new RedisOption();
                t = factory(option);
                if (option.ExpiresAt != null) SetRedisItem(key, t, option.ExpiresAt);
                else SetRedisItem(key, t);
            }
            else
            {
                if (type.IsValueType || type == typeof(string))
                {
                    t = (TItem)Convert.ChangeType(str, type);

                }
                else
                {
                    t = JsonConvert.DeserializeObject<TItem>(str);
                }

            }
            return t;
        }

        public class RedisOption
        {
            public DateTime? ExpiresAt { get; set; }
        }

        /// <summary>
        /// redis获取自增值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public long IncrementRedisItem(string key, int incrValue = 1)
        {
            key = context.Membership.OnRedisKey(key);

            //IDatabase client = RedisClient.GetDatabase(DataBaseIndex);
            return RedisClient.IncrBy(key, incrValue);
        }

        public void Dispose()
        {
            RedisClient.Dispose();
        }
    }
}